﻿using Core.DataAccess.Model;
using Core.Framework;
using DotNetty.Framework;
using DotNetty.Framework.BaseTriggers;
using iTool.Connector.CommandOfParameter;
using Grain.Interfaces;
using iTool.ClusterComponent;
using Local.Interface;
using Newtonsoft.Json;
using System.Threading.Tasks;

namespace iTool.Connector.CommandWorkers
{

    [Worker("iTool Cloud")]
    public class CloudFunctionWorker : WorkerController
    {
        private readonly ICloudFunction iCloudFunction;
        private readonly INodeInstallPackage iNodeInstallPackage;
        private readonly iToolClusterHostClient iCluster;
        private readonly ProducerQueueHandler producerQueueHandlerOfInstall;
        private readonly ProducerQueueHandler producerQueueHandlerOfScriptBudiler;

        public CloudFunctionWorker(ICloudFunction cloudFunction, INodeInstallPackage nodeInstallPackage, iToolClusterHostClient cluster)
        {
            this.iCloudFunction = cloudFunction;
            this.iNodeInstallPackage = nodeInstallPackage;
            this.iCluster = cluster;
            this.producerQueueHandlerOfInstall = new ProducerQueueHandler(AppSetting.INSTALLPACKAGETOPIC, AppSetting.QueueServiceStreamNamespace);
            this.producerQueueHandlerOfScriptBudiler = new ProducerQueueHandler(AppSetting.ScriptBudilerTopic, AppSetting.QueueServiceStreamNamespace);
        }

        /// <summary>
        /// 获取函数列表
        /// </summary>
        /// <returns></returns>
        [MethodRoute("Get Functions")]
        public async Task<DoWorkResponse> GetFunctions(HandleDoWorkingContext context)
        {
            var module = this.iCluster.GetService<IEditCloudFunctionListService>();
            var result = await module.GetFilesDetail();
            return this.GetWorkResponse(context, result);
        }

        /// <summary>
        /// 更新函数
        /// </summary>
        /// <returns></returns>
        [MethodRoute("Update $moduleName")]
        public async Task<DoWorkResponse> Update(HandleDoWorkingContext context, string moduleName)

        {
            var parameter = context.Message.GetParameterModel<CloudFunctionParameterOfModify>();
            var module = this.iCluster.GetService<IEditCloudFunctionService>(moduleName);
            await module.Modify(parameter.ScriptContext);

            this.iNodeInstallPackage.InstallPackages(async commands =>
            {
                await this.producerQueueHandlerOfInstall.SendMessageAsync(JsonConvert.SerializeObject(commands));
            }, parameter.Packages);

            return this.GetWorkResponse(context, 1);
        }

        /// <summary>
        /// 添加云函数
        /// </summary>
        /// <returns></returns>
        [MethodRoute("Add Function")]
        public async Task<DoWorkResponse> Add(HandleDoWorkingContext context)

        {
            var parameter = context.Message.GetParameterModel<CloudFunctionParameterOfAdd>();

            var function = new Function
            {
                modulePath = CloudDataConver.GetFunctionFilePathByModuleName(parameter.ModuleName),// $"./CloudFunctions/{parameter.ModuleName}",
                moduleName = parameter.ModuleName,
                scriptContent = parameter.ScriptContext,
                isUseState = parameter.IsUseState
            };

            // 添加云函数
            var methodResult = this.iCloudFunction.Add(async commands =>
            {
                await this.producerQueueHandlerOfScriptBudiler.SendMessageAsync(JsonConvert.SerializeObject(commands));
            }, function);

            if (methodResult.IsFinished)
            {
                var module = this.iCluster.GetService<IEditCloudFunctionListService>();
                await module.AddTemporaryFunction(parameter.IsUseState, function.moduleName, null);

                // installpackage
                this.iNodeInstallPackage.InstallPackages(async commands =>
                {
                    await this.producerQueueHandlerOfInstall.SendMessageAsync(JsonConvert.SerializeObject(commands));
                }, parameter.Packages);
            }
            else
            {
                return this.GetErrorResponseOfParameterValidationFailed(context, methodResult.Discription);
            }

            return this.GetWorkResponse(context, methodResult.IsFinished ? 1 : 0);
        }

        /// <summary>
        /// 删除指定文件
        /// </summary>
        /// <typeparam name="TMessage"></typeparam>
        /// <param name="context"></param>
        /// <param name="moduleName"></param>
        /// <returns></returns>
        [MethodRoute("Remove $moduleName")]
        public async Task<DoWorkResponse> Remove(HandleDoWorkingContext context, string moduleName)
        {
            int result = 0;
            string modulePath = CloudDataConver.GetFunctionFilePathByModuleName(moduleName);

            var iReminders = this.iCluster.GetService<IReminderService>();

            if (!await iReminders.IsExistByModulePath(modulePath))
            {
                var module = this.iCluster.GetService<IEditCloudFunctionService>(moduleName);
                await module.Remove();
                result = 1;
            }

            return this.GetWorkResponse(context, result);

        }

        /// <summary>
        /// 获取指定模块
        /// </summary>
        /// <typeparam name="TMessage"></typeparam>
        /// <param name="context"></param>
        /// <param name="moduleName"></param>
        /// <returns></returns>
        [MethodRoute("Get $moduleName")]
        public async Task<DoWorkResponse> GetModuleByName(HandleDoWorkingContext context, string moduleName)

        {
            var module = this.iCluster.GetService<IEditCloudFunctionService>(moduleName);
            var result = await module.GetDetail();
            return this.GetWorkResponse(context, result);
        }

        /// <summary>
        /// 推出编辑状态
        /// </summary>
        /// <typeparam name="TMessage"></typeparam>
        /// <param name="context"></param>
        /// <param name="moduleName"></param>
        /// <returns></returns>
        [MethodRoute("ExitEdit $moduleName")]
        public async Task<DoWorkResponse> ExitEdit(HandleDoWorkingContext context, string moduleName)

        {
            var parameter = context.Message.GetParameterModel<CloudFunctionParameterOfModify>();
            var module = this.iCluster.GetService<IEditCloudFunctionService>(moduleName);
            await module.ExitEditState(parameter.ScriptContext);
            return this.GetWorkResponse(context, 1);
        }

        /// <summary>
        /// 进入编辑状态
        /// </summary>
        /// <typeparam name="TMessage"></typeparam>
        /// <param name="context"></param>
        /// <param name="moduleName"></param>
        /// <returns></returns>
        [MethodRoute("EnterEdit $moduleName")]
        public async Task<DoWorkResponse> EnterEdit(HandleDoWorkingContext context, string moduleName)

        {
            var parameter = context.Message.GetParameterModel<CloudFunctionParameterOfModify>();
            var module = this.iCluster.GetService<IEditCloudFunctionService>(moduleName);
            await module.Edit(parameter.ScriptContext, context.Channel);
            return this.GetWorkResponse(context, 1);
        }

        /// <summary>
        /// 添加临时文件
        /// </summary>
        /// <typeparam name="TMessage"></typeparam>
        /// <param name="context"></param>
        /// <param name="moduleName"></param>
        /// <returns></returns>
        [MethodRoute("AddTemporaryFunction")]
        public async Task<DoWorkResponse> AddTemporaryFunction(HandleDoWorkingContext context)
        {
            var parameter = context.Message.GetParameterModel<CloudFunctionParameterOfAdd>();
            var module = this.iCluster.GetService<IEditCloudFunctionListService>();
            await module.AddTemporaryFunction(parameter.IsUseState, parameter.ModuleName, context.Channel);
            return this.GetWorkResponse(context, 1);
        }


    }
}